﻿Imports TyranntEngine

Public Class UserDatabaseAccess

    Private db As New TyranntUserDatasourceDataContext
    Private keyGen As New RandomKeyGenerator
    Private _LastError As New Exception
    Private _naz As New Nabaztag

    Public Function GetUserID(ByVal username As String) As Integer
        Try
            Dim result = (From user In db.users _
                                 Where user.username = username _
                                 Select user).ToList
            If result.Count = 0 Then
                Return -1
            Else
                Return result(0).userID
            End If
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function GetUserID(ByVal username As String, ByVal password As String) As Integer
        Try
            Dim result = (From user In db.users _
                                 Where user.username = username And user.password = password _
                                 Select user).ToList
            If result.Count = 0 Then
                Return -1
            Else
                Return result(0).userID
            End If
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function GetUserIDFromToken(ByVal tokenString As String) As Integer
        Try
            Dim result = (From token In db.tokens _
                          Where token.tokenString = tokenString _
                          Select token).ToList
            If result.Count = 0 Then
                Return -1
            Else
                Return result(0).userID
            End If
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function GetUserIDFromEmail(ByVal email As String) As Integer
        Try
            Dim result = (From user In db.users _
                                 Where user.email = email _
                                 Select user).ToList
            If result.Count = 0 Then
                Return -1
            Else
                Return result(0).userID
            End If
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function GetUserGroup(ByVal token As String) As Integer
        Dim userID = GetUserIDFromToken(token)
        If userID < 0 Then
            Return userID
        End If

        Return GetUserGroup(userID)
    End Function

    Public Function GetUserGroup(ByVal ID As Integer) As Integer
        Try
            Dim result = (From user In db.users _
                          Where user.userID = ID _
                          Select user).ToList
            If result.Count = 0 Then
                Return -1
            Else
                Return result(0).userGroup
            End If
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function GetUserAlias(ByVal token As String) As String
        Dim userID = GetUserIDFromToken(token)
        If userID < 0 Then
            Select Case userID
                Case -1
                    Return "[#]usernotexist"
                Case -2
                    Return Failed("GetUserIDFromToken")
                Case Else
                    Return "[#]unknownerror[" + userID.ToString + "]"
            End Select
        End If
        Return GetUserAlias(userID)
    End Function

    Public Function GetUserAlias(ByVal userID As Integer) As String
        Try
            Dim result = (From user In db.users _
                        Where user.userID = userID _
                        Select user).ToList
            If result.Count = 0 Then
                Return "[#]usernotexist"
            Else
                Return result(0).alias
            End If
        Catch ex As Exception
            _LastError = ex
            Return Failed("GetUserAlias")
        End Try
    End Function

    Public Function GetUsername(ByVal token As String) As String
        Dim userID = GetUserIDFromToken(token)
        If userID < 0 Then
            Select Case userID
                Case -1
                    Return "[#]usernotexist"
                Case -2
                    Return Failed("GetUserIDFromToken")
                Case Else
                    Return "[#]unknownerror[" + userID.ToString + "]"
            End Select
        End If
        Return GetUsername(userID)
    End Function

    Public Function GetUsername(ByVal userID As Integer) As String
        Try
            Dim result = (From user In db.users _
                        Where user.userID = userID _
                        Select user).ToList
            If result.Count = 0 Then
                Return "[#]usernotexist"
            Else
                Return result(0).username
            End If
        Catch ex As Exception
            _LastError = ex
            Return Failed("GetUsername")
        End Try
    End Function

    Public Function GetToken(ByVal userID As Integer) As token
        Try
            Dim result = (From token In db.tokens _
                         Where token.userID = userID _
                         Select token).ToList
            If result.Count = 0 Then
                Return New token
            Else
                Return result(0)
            End If
        Catch ex As Exception
            _LastError = ex
            Return Nothing
        End Try
    End Function

    Public Function GenerateToken(ByVal userID As Integer) As String
        Dim token As token = GetToken(userID)
        If IsNothing(token) Then
            Return Failed("GetToken")
        End If
        If token.tokenString = "" Then
            Try
                Dim aToken As New token
                aToken.tokenString = keyGen.Generate
                aToken.userID = userID
                db.tokens.InsertOnSubmit(aToken)
                db.SubmitChanges()
                Return aToken.tokenString
            Catch ex As Exception
                _LastError = ex
                Return Failed("GenerateToken")
            End Try
        Else
            Return token.tokenString
        End If
    End Function

    Public Function DeleteToken(ByVal userID As Integer) As String
        Dim token As token = GetToken(userID)
        If IsNothing(token) = True Then
            Return Failed("GetToken")
        End If
        If token.tokenString <> "" Then
            Try
                db.tokens.DeleteOnSubmit(token)
                db.SubmitChanges()
                Return ""
            Catch ex As Exception
                _LastError = ex
                Return Failed("DeleteToken")
            End Try
        Else
            Return "[#]usernotexist[DeleteToken]"
        End If
    End Function

    Public Function AddUser(ByVal username As String, ByVal password As String, ByVal userAlias As String, ByVal email As String, ByVal userGroup As Integer) As String
        ' first check if username already exists
        Dim userID = GetUserID(username)
        If userID = -2 Then
            Return Failed("GetUserID")
        End If
        If userID <> -1 Then
            Return "[#]userexists"
        End If

        ' Now we check to see if the email already exists
        userID = GetUserIDFromEmail(email)
        If userID = -2 Then
            Return Failed("GetUserIDFromEmail")
        End If
        If userID <> -1 Then
            Return "[#]emailexists"
        End If

        ' We are now sure that this is a new user so add the new user
        Try
            Dim aUser As New user
            aUser.username = username
            aUser.password = password
            aUser.alias = userAlias
            aUser.email = email
            aUser.userGroup = userGroup
            db.users.InsertOnSubmit(aUser)
            db.SubmitChanges()
        Catch ex As Exception
            _LastError = ex
            Return Failed("AddUser")
        End Try

        ' We have now added the user so lets get a token for this user
        userID = GetUserID(username)
        If userID = -2 Then
            Return Failed("GetUserID")
        End If
        Return GenerateToken(userID)
    End Function

    Public Function RemoveUser(ByVal userID As Integer) As String
        ' firstly we need to delete any token for this user
        ' we are not worried in this case if there is one.
        Dim result As String = DeleteToken(userID)
        If result.Contains("[#]usernotexist") = False Then
            If result <> "" Then
                Return result
            End If
        End If

        ' To Do Delete all users for this character

        ' Now we need the actual user object to delete
        Dim aUser As user = GetUser(userID)
        If IsNothing(aUser) Then
            Return Failed("GetUser")
        End If

        ' Now finally delete the user
        Try
            db.users.DeleteOnSubmit(aUser)
            db.SubmitChanges()
            Return ""
        Catch ex As Exception
            _LastError = ex
            Return Failed("RemoveUser")
        End Try
    End Function

    Public Function ChangeUserGroup(ByVal userID As Integer, ByVal newGroup As Integer) As String
        Dim aUser As user = GetUser(userID)
        If IsNothing(aUser) Then
            Return Failed("GetUser")
        End If

        Try
            aUser.userGroup = newGroup
            db.SubmitChanges()
            Return ""
        Catch ex As Exception
            _LastError = ex
            Return Failed("ChangeUserGoup")
        End Try
    End Function

    Public Function GetUser(ByVal userID As Integer) As user
        Try
            Dim result = (From user In db.users _
                         Where user.userID = userID _
                         Select user).ToList
            If result.Count = 0 Then
                Return Nothing
            Else
                Return result(0)
            End If
        Catch ex As Exception
            _LastError = ex
            Return Nothing
        End Try
    End Function

    Public Function GetUserList(ByVal userGroup As Integer) As String
        Try
            Select Case userGroup
                Case 1
                    Dim userListXML = <users>
                                          <%= From user In db.users _
                                              Select <user id=<%= user.userID %>>
                                                         <name><%= user.username %></name>
                                                         <alias><%= user.alias %></alias>
                                                         <group><%= user.userGroup %></group>
                                                         <email><%= user.email %></email>
                                                     </user> %>
                                      </users>
                    Return userListXML.ToString
                Case 2
                    Dim userListXML = <users>
                                          <%= From token In db.tokens _
                                              Select <user name=<%= token.user.username %>></user> %>
                                      </users>
                    Return userListXML.ToString
                Case Else
                    Return "[#]invalidgroup"
            End Select
        Catch ex As Exception
            _LastError = ex
            Return Failed("GetUserList")
        End Try
    End Function

    Public Function GetUserCount() As Integer
        Try
            Dim result = From user In db.users _
                         Select user
            Return result.Count
        Catch ex As Exception
            _LastError = ex
            Return -2
        End Try
    End Function

    Public Function ChangePassword(ByVal userID As Integer, ByVal newPassword As String) As String
        Dim aUser As user = GetUser(userID)
        If IsNothing(aUser) Then
            Return Failed("GetUser[" + userID.ToString + "]")
        End If

        Try
            aUser.password = newPassword
            db.SubmitChanges()
            Return ""
        Catch ex As Exception
            _LastError = ex
            Return Failed("ChangePassword")
        End Try
    End Function

    Public Function SetMOTD(ByVal aMessage As String) As String
        Try
            Dim result = From message In db.messages _
                         Where message.messageID = 1 _
                         Select message
            If result.Count = 0 Then
                Dim newMOTD As New message
                newMOTD.messageID = 1
                newMOTD.message = aMessage
                db.messages.InsertOnSubmit(newMOTD)
                db.SubmitChanges()
            Else
                result(0).message = aMessage
                db.SubmitChanges()
            End If
            Return ""
        Catch ex As Exception
            _LastError = ex
            Return ex.ToString
        End Try
    End Function

    Public ReadOnly Property LastError() As Exception
        Get
            Return _LastError
        End Get
    End Property

    Public Function Failed(ByVal routine As String) As String
        _naz.SendMessage("fatal error", "Fatal error in routine " + routine + ". Exception caught!", Nabaztag.VoicesEnum.UK_Edwin)
        Return "[#]failed[" + routine + "]|" + _LastError.ToString
    End Function
End Class
